package com.yinshan.avchatkit.activity;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.Toast;

import com.github.zackratos.ultimatebar.UltimateBar;
import com.hjq.toast.ToastUtils;
import com.netease.nimlib.sdk.NIMClient;
import com.netease.nimlib.sdk.Observer;
import com.netease.nimlib.sdk.StatusCode;
import com.netease.nimlib.sdk.auth.AuthServiceObserver;
import com.netease.nimlib.sdk.auth.ClientType;
import com.netease.nimlib.sdk.avchat.AVChatManager;
import com.netease.nimlib.sdk.avchat.constant.AVChatControlCommand;
import com.netease.nimlib.sdk.avchat.constant.AVChatEventType;
import com.netease.nimlib.sdk.avchat.constant.AVChatType;
import com.netease.nimlib.sdk.avchat.model.AVChatAudioFrame;
import com.netease.nimlib.sdk.avchat.model.AVChatCalleeAckEvent;
import com.netease.nimlib.sdk.avchat.model.AVChatCommonEvent;
import com.netease.nimlib.sdk.avchat.model.AVChatControlEvent;
import com.netease.nimlib.sdk.avchat.model.AVChatData;
import com.netease.nimlib.sdk.avchat.model.AVChatOnlineAckEvent;
import com.netease.nimlib.sdk.avchat.model.AVChatVideoFrame;
import com.netease.nimlib.sdk.msg.MsgService;
import com.netease.nimlib.sdk.msg.MsgServiceObserve;
import com.netease.nimlib.sdk.msg.constant.SessionTypeEnum;
import com.netease.nimlib.sdk.msg.model.CustomNotification;
import com.yinshan.avchatkit.AVChatKit;
import com.yinshan.avchatkit.AVChatProfile;
import com.yinshan.avchatkit.R;
import com.yinshan.avchatkit.common.activity.UI;
import com.yinshan.avchatkit.common.log.LogUtil;
import com.yinshan.avchatkit.constant.AVChatExitCode;
import com.yinshan.avchatkit.controll.AVChatController;
import com.yinshan.avchatkit.controll.AVChatSoundPlayer;
import com.yinshan.avchatkit.module.AVChatTimeoutObserver;
import com.yinshan.avchatkit.module.SimpleAVChatStateObserver;
import com.yinshan.avchatkit.notification.AVChatNotification;
import com.yinshan.avchatkit.receiver.PhoneCallStateObserver;
import com.yinshan.avchatkit.ui.AVChatVideoUI;

/**
 * 音视频主界面
 * 1、初始化
 * 2、来电去电入口
 * 3、监听
 * 4、切换音视频
 * 5、通知栏提醒
 * 6、faceU
 * Created by winnie on 2017/12/10.
 */

public class AVChatActivity extends UI {
    // constant
    private static final String TAG = "AVChatActivity";
    private static final String KEY_IN_CALLING = "KEY_IN_CALLING";
    private static final String KEY_ACCOUNT = "KEY_ACCOUNT";
    private static final String KEY_DISPLAY_NAME = "KEY_DISPLAY_NAME";
    private static final String KEY_SOURCE = "source";
    private static final String KEY_CALL_CONFIG = "KEY_CALL_CONFIG";
    private static final String KEY_CALL_EXTRA = "KEY_CALL_EXTRA";

    public static final String KEY_FACE_STATUS = "faceStatus";
    //面签状态广播
    public static final String ACTION_SINGAL_STATUS = "comm.yinshan.avchatkit.face.status";
    public static final String FACE_STATUS_RECORD_FINISH = "FACE_STATUS_RECORD_FINISH";
    //视频成功拨出去
    public static final String FACE_STATUS_SERVER_START = "FACE_STATUS_SERVER_START";

    public static final String STEP_SIGNAL_CALL_CONNECT = "STEP_SIGNAL_CALL_CONNECT"; //通话接通（客户端发出，服务端监听）（通话接通时发送）
    public static final String STEP_SIGNAL_CALL_NOT_CONNECT = "STEP_SIGNAL_CALL_NOT_CONNECT"; //通话未接通（客户端发出，服务端监听）（拒绝、超时、忙线、呼叫失败时发送）
    public static final String STEP_SIGNAL_FACE_REC_START = "STEP_SIGNAL_FACE_REC_START"; //开始人脸识别（座席端发出，客户端监听）（点击人脸识别时发送）
    public static final String STEP_SIGNAL_FACE_REC_READY = "STEP_SIGNAL_FACE_REC_READY"; //人脸识别文件已上传（客户端发出，坐席端监听）（人脸视频上传完调用识别接口后发送）
    public static final String STEP_SIGNAL_FACE_REC_SUCCESS = "STEP_SIGNAL_FACE_REC_SUCCESS"; //人脸识别成功（客户端发出，坐席端监听）（轮询到人脸识别成功状态后发送）
    public static final String STEP_SIGNAL_FACE_REC_FAIL = "STEP_SIGNAL_FACE_REC_FAIL"; //人脸识别失败（客户端发出，坐席端监听）（轮询到人脸识别失败状态后发送）
    public static final String STEP_SIGNAL_RESULT_SUCCESS = "STEP_SIGNAL_RESULT_SUCCESS"; //视频面签通过（座席端发出，客户端监听）（点击面签通过按钮时发送）
    public static final String STEP_SIGNAL_RESULT_FAIL = "STEP_SIGNAL_RESULT_FAIL"; //视频面签未通过（座席端发出，客户端监听）（点击面签失败按钮时发送）


    public static final int FROM_BROADCASTRECEIVER = 0; // 来自广播
    public static final int FROM_INTERNAL = 1; // 来自发起方
    public static final int FROM_UNKNOWN = -1; // 未知的入口

    //人脸识别广播
    private FaceReceiver faceReceiver;
    private LocalBroadcastManager localBroadcastManager;
    // view
    private View root;
    private View videoRoot;
    private View surfaceRoot;
    private RelativeLayout bottomBtn;

    // state
    private static boolean needFinish = true; // 若来电或去电未接通时，点击home。另外一方挂断通话。从最近任务列表恢复，则finish
    private boolean mIsInComingCall = false;// is incoming call or outgoing call
    private boolean isCallEstablished = false; // 电话是否接通
    private boolean isUserFinish = false;
    private boolean hasOnPause = false; // 是否暂停音视频

    // data
    private AVChatData avChatData; // config for connect video server
    private int state = 2; // calltype 音频或视频
    private String receiverId; // 对方的account
    private String displayName; // 对方的显示昵称
    private String exteraMsg;//额外参数

    private AVChatController avChatController;
    private AVChatVideoUI avChatVideoUI; // 视频界面

    // notification
    private AVChatNotification notifier;

    // 拨打电话
    public static void outgoingCall(Context context, String account, String displayName, String exteraMsg, int source) {
        needFinish = false;
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setClass(context, AVChatActivity.class);
        intent.putExtra(KEY_ACCOUNT, account);
        intent.putExtra(KEY_DISPLAY_NAME, displayName);
        intent.putExtra(KEY_IN_CALLING, false);
        intent.putExtra(KEY_CALL_EXTRA, exteraMsg);
        intent.putExtra(KEY_SOURCE, source);
        context.startActivity(intent);
    }

    // 接听来电
    public static void incomingCall(Context context, AVChatData config, String displayName, int source) {
        needFinish = false;
        Intent intent = new Intent();
        intent.setClass(context, AVChatActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(KEY_CALL_CONFIG, config);
        intent.putExtra(KEY_DISPLAY_NAME, displayName);
        intent.putExtra(KEY_IN_CALLING, true);
        intent.putExtra(KEY_SOURCE, source);
        context.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 若来电或去电未接通时，点击home。另外一方挂断通话。从最近任务列表恢复，则finish
        if (needFinish) {
            finish();
            return;
        }

        // 启动成功，取消timeout处理
        AVChatProfile.getInstance().activityLaunched();

        dismissKeyguard();

        root = LayoutInflater.from(this).inflate(R.layout.avchat_activity, null);
        setContentView(root);

        UltimateBar.Companion.with(this)
                .statusDark(true)                  // 状态栏灰色模式(Android 6.0+)，默认 flase
                .statusDrawable(ContextCompat.getDrawable(this, R.drawable.shape_top_nav_bg))           // 状态栏背景，默认 null
                .statusDrawable2(ContextCompat.getDrawable(this, R.drawable.shape_top_nav_bg))         // Android 6.0 以下状态栏灰色模式时状态栏颜色
                .applyNavigation(false)              // 应用到导航栏，默认 flase
                .navigationDark(true)              // 导航栏灰色模式(Android 8.0+)，默认 false
                .create()
                .drawableBar();

        parseIntent();

        initData();

        showUI();

        registerObserves(true);

        notifier = new AVChatNotification(this);
        notifier.init(receiverId != null ? receiverId : avChatData.getAccount(), displayName);
        startTimer();
    }

    public void startTimer() {
        lastTime = System.currentTimeMillis();
        mHandler.removeCallbacks(runnable);
        mHandler.post(runnable);
    }

    private static long lastTime;
    private Handler mHandler = new Handler();
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            //10秒不操作隐藏底部挂断按钮
            if (System.currentTimeMillis() - lastTime > 10 * 1000) {
                mHandler.removeCallbacks(this);
                bottomBtn.setVisibility(View.GONE);
            } else {
                //每隔1s执行一次Run方法
                mHandler.postDelayed(runnable, 1000);
            }
        }
    };

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        lastTime = System.currentTimeMillis();
        if (bottomBtn.getVisibility() == View.GONE) {
            bottomBtn.setVisibility(View.VISIBLE);
            startTimer();
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onResume() {
        super.onResume();
        cancelCallingNotifier();

        if (hasOnPause) {
            avChatVideoUI.onResume();
            avChatController.resumeVideo();
            hasOnPause = false;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        avChatController.pauseVideo();
        hasOnPause = true;
    }

    @Override
    protected void onStop() {
        super.onStop();
        activeCallingNotifier();
    }


    @Override
    public void onBackPressed() {
        // 禁用返回键
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //界面销毁时强制尝试挂断，防止出现红米Note 4X等手机在切后台点击杀死程序时，实际没有杀死的情况
        try {
            manualHangUp(AVChatExitCode.HANGUP);
        } catch (Exception e) {

        }

        if (avChatVideoUI != null) {
            avChatVideoUI.onDestroy();
        }

        registerObserves(false);
        AVChatProfile.getInstance().setAVChatting(false);
        cancelCallingNotifier();
        needFinish = true;

        //解除人脸监听注册
        localBroadcastManager.unregisterReceiver(faceReceiver);
    }

    // 设置窗口flag，亮屏并且解锁/覆盖在锁屏界面上
    private void dismissKeyguard() {
        getWindow().addFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                        WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                        WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
                        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
        );
    }

    /**
     * ************************ 初始化 ***************************
     */

    private void parseIntent() {
        mIsInComingCall = getIntent().getBooleanExtra(KEY_IN_CALLING, false);
        displayName = getIntent().getStringExtra(KEY_DISPLAY_NAME);
        switch (getIntent().getIntExtra(KEY_SOURCE, FROM_UNKNOWN)) {
            case FROM_BROADCASTRECEIVER: // incoming call
                avChatData = (AVChatData) getIntent().getSerializableExtra(KEY_CALL_CONFIG);
                break;
            case FROM_INTERNAL: // outgoing call
                receiverId = getIntent().getStringExtra(KEY_ACCOUNT);
                exteraMsg = getIntent().getStringExtra(KEY_CALL_EXTRA);
                break;
            default:
                break;
        }
    }

    private void initData() {
        avChatController = new AVChatController(this, avChatData);
        avChatVideoUI = new AVChatVideoUI(this, root, avChatData, displayName, avChatController);
        //注册人脸识别广播监听
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ACTION_SINGAL_STATUS);
        localBroadcastManager = LocalBroadcastManager.getInstance(context);
        faceReceiver = new FaceReceiver();
        localBroadcastManager.registerReceiver(faceReceiver, intentFilter);
    }


    private void registerObserves(boolean register) {
        AVChatManager.getInstance().observeAVChatState(avchatStateObserver, register);
        AVChatManager.getInstance().observeHangUpNotification(callHangupObserver, register);
        AVChatManager.getInstance().observeCalleeAckNotification(callAckObserver, register);
        AVChatManager.getInstance().observeControlNotification(callControlObserver, register);
        AVChatTimeoutObserver.getInstance().observeTimeoutNotification(timeoutObserver, register, mIsInComingCall);
        AVChatManager.getInstance().observeOnlineAckNotification(onlineAckObserver, register);
        PhoneCallStateObserver.getInstance().observeAutoHangUpForLocalPhone(autoHangUpForLocalPhoneObserver, register);
        //放到所有UI的基类里面注册，所有的UI实现onKickOut接口
        NIMClient.getService(AuthServiceObserver.class).observeOnlineStatus(userStatusObserver, register);
        NIMClient.getService(MsgServiceObserve.class).observeCustomNotification(customNotificationObserver, register);
    }

    /**
     * ************************ 音视频来电去电入口 ***************************
     */

    private void showUI() {
        videoRoot = root.findViewById(R.id.avchat_video_layout);
        surfaceRoot = root.findViewById(R.id.avchat_surface_layout);
        bottomBtn = root.findViewById(R.id.real_avchart_btn);
        // 视频
        videoRoot.setVisibility(View.VISIBLE);
        surfaceRoot.setVisibility(View.VISIBLE);
        if (mIsInComingCall) {
            // 来电
            AVChatSoundPlayer.instance().play(AVChatSoundPlayer.RingerTypeEnum.RING);
            avChatVideoUI.showIncomingCall(avChatData);
        } else {
            // 去电
            AVChatSoundPlayer.instance().play(AVChatSoundPlayer.RingerTypeEnum.CONNECTING);
            avChatVideoUI.doOutgoingCall(receiverId, exteraMsg);
        }

        root.findViewById(R.id.img_bind_close).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

    }

    /**
     * ****************************** 监听器 **********************************
     */

    // 通话过程状态监听
    private SimpleAVChatStateObserver avchatStateObserver = new SimpleAVChatStateObserver() {
        @Override
        public void onAVRecordingCompletion(String account, String filePath) {
            if (account != null && filePath != null && filePath.length() > 0) {
                Intent intent = new Intent();
                intent.setAction(ACTION_SINGAL_STATUS);
                intent.putExtra(KEY_FACE_STATUS, FACE_STATUS_RECORD_FINISH);
                intent.putExtra("faceFile", filePath);
                intent.putExtra("account", account);
                LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
                avChatVideoUI.showNotify("", false);
            }
        }

        @Override
        public void onAudioRecordingCompletion(String filePath) {
            if (filePath != null && filePath.length() > 0) {
                String msg = "音频录制已结束, 录制文件已保存至：" + filePath;
                ToastUtils.show(msg);
            }
        }

        @Override
        public void onLowStorageSpaceWarning(long availableSize) {
            //本地内存不足提示
            ToastUtils.show("系统内存不足，请清理无用空间");
        }

        @Override
        public void onJoinedChannel(int code, String audioFile, String videoFile, int i) {
            LogUtil.d(TAG, "audioFile -> " + audioFile + " videoFile -> " + videoFile);
            handleWithConnectServerResult(code);
        }

        @Override
        public void onUserJoined(String account) {
            LogUtil.d(TAG, "onUserJoin -> " + account);
            if (state == AVChatType.VIDEO.getValue()) {
                avChatVideoUI.initLargeSurfaceView(account);
                avChatVideoUI.switchRender(AVChatKit.getAccount(), account);
                if(!mIsInComingCall){
                    sendMsgToIM(STEP_SIGNAL_CALL_CONNECT + ":" + avChatVideoUI.getAvChatData().getChatId());
                }
            }
        }

        @Override
        public void onUserLeave(String account, int event) {
            LogUtil.d(TAG, "onUserLeave -> " + account);
            manualHangUp(AVChatExitCode.HANGUP);
            finish();
        }

        @Override
        public void onCallEstablished() {
            LogUtil.d(TAG, "onCallEstablished");
            //移除超时监听
            AVChatTimeoutObserver.getInstance().observeTimeoutNotification(timeoutObserver, false, mIsInComingCall);
            if (avChatController.getTimeBase() == 0)
                avChatController.setTimeBase(SystemClock.elapsedRealtime());


            // 接通以后，自己是小屏幕显示图像，对方是大屏幕显示图像
            avChatVideoUI.initSmallSurfaceView(AVChatKit.getAccount());
            avChatVideoUI.showVideoInitLayout();

            isCallEstablished = true;
        }

        @Override
        public boolean onVideoFrameFilter(AVChatVideoFrame frame, boolean maybeDualInput) {
            return true;
        }

        @Override
        public boolean onAudioFrameFilter(AVChatAudioFrame frame) {
            return true;
        }

    };

    // 通话过程中，收到对方挂断电话
    Observer<AVChatCommonEvent> callHangupObserver = new Observer<AVChatCommonEvent>() {
        @Override
        public void onEvent(AVChatCommonEvent avChatHangUpInfo) {
            avChatData = avChatController.getAvChatData();
            if (avChatData != null && avChatData.getChatId() == avChatHangUpInfo.getChatId()) {
                hangUpByOther(AVChatExitCode.HANGUP);
                cancelCallingNotifier();
                // 如果是incoming call主叫方挂断，那么通知栏有通知
                if (mIsInComingCall && !isCallEstablished) {
                    activeMissCallNotifier();
                }
            }

        }
    };

    // 呼叫时，被叫方的响应（接听、拒绝、忙）
    Observer<AVChatCalleeAckEvent> callAckObserver = new Observer<AVChatCalleeAckEvent>() {
        @Override
        public void onEvent(AVChatCalleeAckEvent ackInfo) {
            AVChatData info = avChatController.getAvChatData();
            if (info != null && info.getChatId() == ackInfo.getChatId()) {
                if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_BUSY) {
                    hangUpByOther(AVChatExitCode.PEER_BUSY);
                    if (!mIsInComingCall) {
                        sendMsgToIM(STEP_SIGNAL_CALL_NOT_CONNECT + ":" + avChatVideoUI.getAvChatData().getChatId());
                    }
                } else if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_REJECT) {
                    hangUpByOther(AVChatExitCode.REJECT);
                    if (!mIsInComingCall) {
                        sendMsgToIM(STEP_SIGNAL_CALL_NOT_CONNECT + ":" + avChatVideoUI.getAvChatData().getChatId());
                    }
                } else if (ackInfo.getEvent() == AVChatEventType.CALLEE_ACK_AGREE) {
                    AVChatSoundPlayer.instance().stop();
                    avChatController.isCallEstablish.set(true);
                }
            }
        }
    };

    Observer<Integer> timeoutObserver = new Observer<Integer>() {
        @Override
        public void onEvent(Integer integer) {
            manualHangUp(AVChatExitCode.CANCEL);
            // 来电超时，自己未接听
            if (mIsInComingCall) {
                activeMissCallNotifier();
            }
            finish();
        }
    };

    // 监听音视频模式切换通知, 对方音视频开关通知
    Observer<AVChatControlEvent> callControlObserver = new Observer<AVChatControlEvent>() {
        @Override
        public void onEvent(AVChatControlEvent netCallControlNotification) {
            handleCallControl(netCallControlNotification);
        }
    };

    // 处理音视频切换请求和对方音视频开关通知
    private void handleCallControl(AVChatControlEvent notification) {
        if (AVChatManager.getInstance().getCurrentChatId() != notification.getChatId()) {
            return;
        }
        switch (notification.getControlCommand()) {
            case AVChatControlCommand.SWITCH_AUDIO_TO_VIDEO_AGREE:
                // 对方同意切成视频啦
                state = AVChatType.VIDEO.getValue();
                avChatVideoUI.onAudioToVideoAgree(notification.getAccount());
                break;
            case AVChatControlCommand.SWITCH_AUDIO_TO_VIDEO_REJECT:
                rejectAudioToVideo();
                Toast.makeText(AVChatActivity.this, R.string.avchat_switch_video_reject, Toast.LENGTH_SHORT).show();
                break;
            case AVChatControlCommand.NOTIFY_VIDEO_OFF:
                // 收到对方关闭画面通知
                if (state == AVChatType.VIDEO.getValue()) {
                    avChatVideoUI.peerVideoOff();
                }
                break;
            case AVChatControlCommand.NOTIFY_VIDEO_ON:
                // 收到对方打开画面通知
                if (state == AVChatType.VIDEO.getValue()) {
                    avChatVideoUI.peerVideoOn();
                }
                break;
            case 10:
                avChatVideoUI.showCameraError();
                break;
        }
    }

    /**
     * 处理连接服务器的返回值
     *
     * @param auth_result
     */
    protected void handleWithConnectServerResult(int auth_result) {
        LogUtil.i(TAG, "result code->" + auth_result);
        if (auth_result == 200) {
            LogUtil.d(TAG, "onConnectServer success");
        } else if (auth_result == 101) { // 连接超时
            avChatController.showQuitToast(AVChatExitCode.PEER_NO_RESPONSE);
        } else if (auth_result == 401) { // 验证失败
            avChatController.showQuitToast(AVChatExitCode.CONFIG_ERROR);
        } else if (auth_result == 417) { // 无效的channelId
            avChatController.showQuitToast(AVChatExitCode.INVALIDE_CHANNELID);
        } else { // 连接服务器错误，直接退出
            avChatController.showQuitToast(AVChatExitCode.CONFIG_ERROR);
        }
    }

    /**
     * 注册/注销同时在线的其他端对主叫方的响应
     */
    Observer<AVChatOnlineAckEvent> onlineAckObserver = new Observer<AVChatOnlineAckEvent>() {
        @Override
        public void onEvent(AVChatOnlineAckEvent ackInfo) {
            if (state == AVChatType.AUDIO.getValue()) {
                avChatData = avChatController.getAvChatData();
            } else {
                avChatData = avChatVideoUI.getAvChatData();
            }
            if (avChatData != null && avChatData.getChatId() == ackInfo.getChatId()) {
                AVChatSoundPlayer.instance().stop();

                String client = null;
                switch (ackInfo.getClientType()) {
                    case ClientType.Web:
                        client = "Web";
                        break;
                    case ClientType.Windows:
                        client = "Windows";
                        break;
                    case ClientType.Android:
                        client = "Android";
                        break;
                    case ClientType.iOS:
                        client = "iOS";
                        break;
                    case ClientType.MAC:
                        client = "Mac";
                        break;
                    default:
                        break;
                }
                if (client != null) {
                    String option = ackInfo.getEvent() == AVChatEventType.CALLEE_ONLINE_CLIENT_ACK_AGREE ? "接听！" : "拒绝！";
                    ToastUtils.show("通话已在" + client + "端被" + option);
                }
                finish();
            }
        }
    };

    Observer<Integer> autoHangUpForLocalPhoneObserver = new Observer<Integer>() {
        @Override
        public void onEvent(Integer integer) {
            hangUpByOther(AVChatExitCode.PEER_BUSY);
        }
    };

    Observer<StatusCode> userStatusObserver = new Observer<StatusCode>() {

        @Override
        public void onEvent(StatusCode code) {
            if (code.wontAutoLogin()) {
                AVChatSoundPlayer.instance().stop();
                AVChatKit.getAvChatOptions().logout(AVChatActivity.this);
                finish();
            }
        }
    };

    /**
     * 自定义系统通知监听
     */
    private Observer<CustomNotification> customNotificationObserver = new Observer<CustomNotification>() {
        @Override
        public void onEvent(CustomNotification customNotification) {
            switch (customNotification.getContent()) {
                case STEP_SIGNAL_FACE_REC_START:
                    avChatVideoUI.showFaceView(true);
                    avChatVideoUI.showNotify("请将面部对准屏幕方框，即将开始人脸识别", true);
                    getHandler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            avChatVideoUI.showNotify("正在采集人脸信息...", true);
                        }
                    }, 3000);
                    break;
                case STEP_SIGNAL_FACE_REC_READY:
                    avChatVideoUI.showFaceView(false);
                    avChatVideoUI.showNotify("人脸信息已采集，正在识别...");
                    break;
                case STEP_SIGNAL_FACE_REC_FAIL:
                    avChatVideoUI.showNotify("人脸识别失败，请重试", true);
                    break;
                case STEP_SIGNAL_FACE_REC_SUCCESS:
                    avChatVideoUI.showNotify("人脸识别已通过");
                    break;
                case STEP_SIGNAL_RESULT_SUCCESS:
                    sendBroadCast(STEP_SIGNAL_RESULT_SUCCESS);
                    break;
                case STEP_SIGNAL_RESULT_FAIL:
                    sendBroadCast(STEP_SIGNAL_RESULT_FAIL);
                    break;
            }
        }
    };

    private void rejectAudioToVideo() {
        videoRoot.setVisibility(View.GONE);
        surfaceRoot.setVisibility(View.GONE);
    }

    /**
     * ****************** 通知栏 ********************
     */
    private void activeCallingNotifier() {
        if (notifier != null && !isUserFinish) {
            notifier.activeCallingNotification(true);
        }
    }

    private void cancelCallingNotifier() {
        if (notifier != null) {
            notifier.activeCallingNotification(false);
        }
    }

    private void activeMissCallNotifier() {
        if (notifier != null) {
            notifier.activeMissCallNotification(true);
        }
    }

    @Override
    public void finish() {
        isUserFinish = true;
        super.finish();
    }

    // 主动挂断
    private void manualHangUp(int exitCode) {
        releaseVideo();
        avChatController.hangUp(exitCode);
        if (!isCallEstablished && !mIsInComingCall) {
            sendMsgToIM(STEP_SIGNAL_CALL_NOT_CONNECT + ":" + avChatVideoUI.getAvChatData().getChatId());
        }
    }

    // 被对方挂断
    private void hangUpByOther(int exitCode) {
        if (exitCode == AVChatExitCode.PEER_BUSY) {
            avChatController.hangUp(AVChatExitCode.HANGUP);
            finish();
        } else {
            releaseVideo();
            avChatController.onHangUp(exitCode);
        }
    }

    private void releaseVideo() {
        if (state == AVChatType.VIDEO.getValue()) {
            avChatVideoUI.releaseVideo();
        }
    }

    /**
     * 人脸识别结果广播接收
     */
    private class FaceReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (null == intent) return;
            if (ACTION_SINGAL_STATUS.equals(intent.getAction())) {
                switch (intent.getStringExtra(KEY_FACE_STATUS)) {
                    case STEP_SIGNAL_FACE_REC_READY:
                        sendMsgToIM(STEP_SIGNAL_FACE_REC_READY);
                        break;
                    case STEP_SIGNAL_FACE_REC_SUCCESS:
                        ToastUtils.show("已完成人脸识别，正式开始视频面签");
                        avChatVideoUI.resetRecordTip();
                        sendMsgToIM(STEP_SIGNAL_FACE_REC_SUCCESS);
                        break;
                    case STEP_SIGNAL_FACE_REC_FAIL:
                        ToastUtils.show("人脸识别失败，请重新执行一次");
                        avChatVideoUI.resetRecordTip();
                        sendMsgToIM(STEP_SIGNAL_FACE_REC_FAIL);
                        break;
                }
            }
        }
    }

    /**
     * 发消息给远端
     */
    private void sendMsgToIM(String result) {
        CustomNotification notification = new CustomNotification();
        notification.setContent(result);
        notification.setFromAccount(AVChatKit.getAccount());
        notification.setSessionId(receiverId != null ? receiverId : avChatData.getAccount());
        notification.setSessionType(SessionTypeEnum.P2P);
        NIMClient.getService(MsgService.class).sendCustomNotification(notification);
    }

    /**
     * 发送广播
     */
    private void sendBroadCast(String msg) {
        Intent intent = new Intent();
        intent.setAction(ACTION_SINGAL_STATUS);
        intent.putExtra(KEY_FACE_STATUS, msg);
        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
    }
}
